import socket
import time, os

DE_QUIT = 0
DE_COMMAND = 3
DE_FILE = 4
DE_TELL = 5
DE_STATUS = 0


class device:
    def __init__(self, name, role=False, status=0) -> None:
        self.name = name
        self.role = role
        self.status = status
        self.soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def test(self):
        print("Sub thread test")
        print(self.__dict__)


class doll(device):
    def __init__(
        self, name, role="doll", status=0, bindPort=12345, bindIP="0.0.0.0", queue=5
    ) -> None:
        super().__init__(name, role, status)
        self.bindIP = bindIP
        self.bindPort = bindPort
        self.queue = queue
        self.soc.bind((bindIP, bindPort))
        self.soc.setblocking(True)
        self.soc.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)

    def startServices(self) -> None:
        self.soc.listen(self.queue)
        print("start listening...")
        self.link, self.master = self.soc.accept()
        self.status = 1
        print("Get a new connecting from", self.master)
        self.link.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
        while True:
            print("lis", end=" ")
            try:
                self.msgGet(self.link.recv(1024).decode())
            except ConnectionResetError:
                self.status = 0
                break

    def msgGet(self, data) -> dict:
        self.link.send(str({"type": DE_TELL, "value": "ok"}).encode())
        msgtype = data[data.find("type") + 7]
        msgvalue = data[data.find("value") + 9 : data.find("}") - 1]
        # print(data, msgtype, msgvalue)
        if int(msgtype) == 3:
            os.system(msgvalue)
        elif int(msgtype) == 4:
            self.fileTrans(msgvalue)
        elif int(msgtype) == 5:
            print("\nmaster say: " + msgvalue)
        else:
            return {}

    def fileTrans(self, fn):
        print("start listening")
        path = './file_get/out.txt'
        fd = self.link.recv(1024)
        if fd.startswith(b"File not found!"):
            print(fd.decode())
        else:
            with open(path, "wb") as f:
                f.write(fd)
            print("File downloaded successfully!")

    def restartCheck(self):
        while self.status == 0:
            self.startServices()


class master(device):
    def __init__(self, name, role="master"):
        super().__init__(name, role)
        self.dolls = False
        self.inuse = False
        self.soc.setblocking(True)
        self.soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.soc.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)

    def connect(self, target="127.0.0.1", dport=12345) -> object or int:
        if self.dolls is not False:
            print("host already connect")
            return 0
        try:
            self.soc.connect((target, dport))
            self.dolls = target
            self.inuse = True
        except:
            print(target, ":", dport, " connect fail", sep="")

    def interface(self) -> int:
        print("设备: ")
        print("3: 向设备运行指令")
        print("4: 向设备传输文件")
        print("5: 即时通信")
        print("99: 退出系统")
        choice = input("您的选项: ")
        return choice

    def switch(self, choice) -> int:
        try:
            choice = int(choice)
        except ValueError:
            print("what???")
            return -1

        if choice == 1:
            print(self.dolls)
            return 0
        elif choice == 2:
            self.connect(target=input("目标地址:"))
            return 0
        elif choice == 3:
            cmd = input("命令:")
            self.soc.send(str({"type": DE_COMMAND, "value": cmd}).encode())
            return 0
        elif choice == 4:
            self.sendFile()
            return 0
        elif choice == 5:
            data = input("tell what:")
            self.soc.send(str({"type": DE_TELL, "value": data}).encode())
            return 0
        elif choice == 99:
            print("exit...")
            self.soc.close()
            self.inuse == False
            return 1
        else:
            print("wrongchoice")
            return 0

    def recvX(self) -> None:
        while self.dolls:
            self.msgGet(self.soc.recv(1024).decode())

    def msgGet(self, data) -> dict:
        if data == "ok":
            print("peer reveived.")
        else:
            # dataDic = dict(data)
            print(data)

    def sendFile(self):
        path = input("file path is: ")
        fn = 1
        self.soc.send(str({"type": DE_FILE, "value": fn}).encode())
        respond = self.soc.recv(1024).decode()
        while respond != "{'type': 5, 'value': 'ok'}":
            print("peer Error")
            return -1
        try:
            print('File Trans start...')
            time.sleep(0.5)
            with open(path, "rb") as f:
                data = f.read()
            self.soc.send(data)
            print("File Trans complit")
        except FileNotFoundError:
            self.soc.send(b'File not found!')
            print("File not found")

    def control(self) -> None:
        while True:
            if self.switch(self.interface()) == 1:
                break
